/**
    算法描述：
    核心问题：
    解决所需数据结构+算法：
**/
#include<bits/stdc++.h>
using namespace std;

struct edge {
    int x, y, pre;
}a[2000010];

int alen, last[20010];
int id = 0, low[20010], dfn[20010], cnt = 0;
int top = -1, st[20010] = {0};
bool v[20010] = {false};

void insert(int x, int y) {
    a[++alen] = edge{x, y, last[x]};
    last[x] = alen;
}

void dfs(int x) {
    dfn[x] = low[x] = ++id;
    st[++top] = x;
    v[x] = true;
    for (int k = last[x]; k; k = a[k].pre) {
        int y = a[k].y;
        if (dfn[y] == 0) {
            dfs(y);
            low[x] = min(low[x], low[y]);
        } else {
            if (v[y])
                low[x] = min(low[x], dfn[y]);
        }
    }
    if(low[x] == dfn[x]) {
        cnt++;
        int y;
        do {
            y = st[top--];
            v[y] = false;
        } while (y != x);
        
    }
}

int main() {
    int n, m;
    scanf("%d%d", &n, &m);
    alen = 0;
    memset(last, 0, sizeof(last));
    while(m--) {
        int x, y;
        scanf("%d%d", &x, &y);
        insert(x, y);
    }
    memset(dfn, 0, sizeof(dfn));
    memset(low, 0, sizeof(low));
    for (int i=1; i<=n; i++) {
        if(!dfn[i])
            dfs(i);
    }
    printf("%d\n", cnt);
    return 0;
}